using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ActorController : MonoBehaviour {
	
	//Movement members
	public float SpeedMax;
	public float ForceMax;
	public float MoveForce;
	public float SpeedFloor; //minimum speed the actor can be moving before the actor stops
	private Vector3 forceVec;
	private Vector3 heading;
	private float speedSqr; //speed of actor at current frame squared; see docs for why we're storing this value
	private float availableForceSqr; //force available for actor to use this frame
	
	private HealthInfo health;
	//private AnimationProcessor processor;

	public bool IsAlive
	{
		get { return health.IsAlive; }
	}
	
	public float Health
	{
		get { return health.Health; }
	}
	
	public HealthInfo HealthInfo
	{
		get { return (health != null) ? health : GetComponent<HealthInfo>(); }
	}

	public Vector3 Heading
	{
		get { return heading; }
	}
	
	// Use this for initialization
	void Start () {
		//init movement
		forceVec = new Vector3();
		health = GetComponent<HealthInfo>();
	}
	
	// Update is called once per frame
	void Update () {
	}
	
	void FixedUpdate()
	{
		//handle movement
		//if we're moving really slowly, just halt so we don't appear to be slipping
		if(speedSqr < Mathf.Pow(SpeedFloor, 2))
		{
			rigidbody.velocity = new Vector3(0.0f, rigidbody.velocity.y, 0.0f);
		}
		//if we're dead, play a death animation
		if(!IsAlive)
		{
            onDeath();
		}
	}

	public void Move(Vector3 direction)
	{
		if(IsAlive)
		{
			//update physical properties
			forceVec = Vector3.zero;
			speedSqr = rigidbody.velocity.sqrMagnitude;
			availableForceSqr = Mathf.Pow(ForceMax, 2);
			float altitude = transform.position.y;
			Vector3 finalMove = new Vector3(direction.x * MoveForce,
			                                0,
			                                direction.z * MoveForce);
			//compose the velocity vector first
			//...a little easier than I thought it'd be
			addForce(finalMove);
			
			//and apply the force
			rigidbody.AddRelativeForce(forceVec);
			heading = finalMove.normalized;
		}
	}
	
	//add a MoveTo method?
	
	private void addForce(Vector3 force)
	{
		Vector3 finalForce = force;
		
		//can we still move this frame?
		if(ForceMax >= 0.0f)
		{
			if(availableForceSqr > 0.0f)
			{
				if(availableForceSqr < force.sqrMagnitude)
				{
					//rescale vector to remaining force
					finalForce = finalForce.normalized * Mathf.Sqrt(availableForceSqr);
				}
				availableForceSqr -= force.sqrMagnitude;
				forceVec += finalForce;
			}
		}
		else
		{
			forceVec += finalForce;
		}
		
		//if we're moving at our speed cap, rescale our force
		if(SpeedMax >= 0.0f && speedSqr >= Mathf.Pow(SpeedMax, 2))
		{
			rigidbody.velocity = rigidbody.velocity.normalized * SpeedMax;
			//return;
		}
	}

    private void onDeath()
    {
        //do stuff on death here
        //Destroy(gameObject);
        //also have event system notify that a death ocurred
    }
}
